type TCallback = (...props: any) => any

export default class EventCenter<T extends string> {
  center: {
    [K: string]: {
      [K: string]: TCallback[]
    }
  };

  constructor() {
    this.center = {};
  }

  // on 订阅
  on(nameSpace: T, type: string, func: TCallback) {
    if (typeof func !== 'function') {
      console.error('event-center func mast be a function');
      return;
    }
    this.center[nameSpace] = this.center[nameSpace] || {[type]: []};
    this.center[nameSpace][type].push(func);
  }

  // 一次订阅
  // once(type, fun) {
  //   let onceFun = () => {
  //     fun(),
  //       this.off()
  //   }
  //   this.on(type, onceFun)
  // }
  // emit 触发
  trigger(nameSpace: T, type: string, ...param: any) {
    const subscribers = this.center[nameSpace]?.[type];
    if (!subscribers) return;
    for (let task of subscribers) {
      task.call(this, ...param);
    }
  }

  // off 释放
  off(nameSpace: T, type: string, func: TCallback) {
    const tasks = this.center[nameSpace][type];
    if (!tasks) return;
    for (let i = 0; i < tasks.length; i++) {
      if (func === tasks[i]) {
        tasks.splice(i, 1);
        break;
      }
    }
  }

  // 绑定命名空间
  bind(nameSpace: T) {
    return {
      on: this.on.bind(this, nameSpace),
      trigger: this.trigger.bind(this, nameSpace),
      off: this.off.bind(this, nameSpace),
      info: this.info,
    };
  }

  // 检查队列大小
  info() {
    return this.center;
  }
}

const eventCenter = new EventCenter();

export const useEventCenter = (nameSpace: string) => {
  return eventCenter.bind(nameSpace);
};